import axios from 'axios';
import { ElMessage } from 'element-plus';
import { useAppUserStore } from '@/stores';
import router from '@/router';
import { showLoading, hideLoading } from '@/utilities/loading';

const baseURL = import.meta.env.DEV ? '' : 'https://www.battor.site:50443';

export { baseURL };

/* 默认的请求工具 */
const instance = axios.create({
  baseURL,
  timeout: 30000
});

// 需要请求拦截器排除的 Url 数组
const requestInterceptorExcludeUrls = [
  '/api/AppUser/AppUserLogin', // 登录
  '/api/AppUser/RefreshToken', // 刷新令牌
  '/api/AppUser/SendRegisterVerifyCodeMail', // （注册）获取邮件验证码
  '/api/AppUser/CreateUser', // 注册
  '/api/AppUser/SendForgetPasswdVerifyCodeMail', // （忘记密码）获取邮件验证码
  '/api/AppUser/ResetAppUserPassword' // 忘记密码
];

// 是否正在刷新令牌
let isRefreshingToken = false;
// 等待（刷新令牌）的请求数组
let pendingRequestArr = [];

// 请求拦截器
instance.interceptors.request.use(
  async (config) => {
    const appUserStore = useAppUserStore();

    // 如果 Url 在排除的范围内，则直接执行后续操作
    if (requestInterceptorExcludeUrls.indexOf(config.url) !== -1) return config;

    // 如果没有 token，则跳转登录页
    if (!appUserStore.tokenObj || !appUserStore.tokenObj.token) {
      console.warn('没有用户 token，跳转登录页');
      router.push('/login');
    }

    showLoading();

    // token 在有效期内，则正常执行后续操作
    if (appUserStore.isUserTokenValid()) {
      config.headers.Authorization = `Bearer ${appUserStore.tokenObj.token}`;
      return config;
    }

    if (!isRefreshingToken) {
      // token 不在有效期内，尝试刷新 token
      isRefreshingToken = true;
      appUserStore.refreshToken().then((refreshResult) => {
        isRefreshingToken = false;

        if (!refreshResult) {
          // 令牌刷新失败，则重置状态，跳转登录页
          pendingRequestArr = [];
          router.push('/login');
        } else {
          // 令牌刷新成功，依次执行等待队列中的请求
          pendingRequestArr.forEach((doRequest) =>
            doRequest(appUserStore.tokenObj.token)
          );
          // 清空队列
          pendingRequestArr = [];
        }
      });
    }

    // 将请求（当前和未来可能的请求）放入等待数组中
    let pendingRequestPromise = new Promise((resolve) => {
      // 将 resolve 封装在 闭包中，执行闭包时才能触发 Promise 的 resolve 方法
      pendingRequestArr.push((newToken) => {
        config.headers.Authorization = `Bearer ${newToken}`;
        resolve(config);
      });
    });

    // 返回一个 Promise 对象
    return pendingRequestPromise;
  },
  (err) => {
    hideLoading();
    Promise.reject(err);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (res) => {
    hideLoading();
    if (res.data && res.data.success) {
      return res.data;
    } else {
      ElMessage.error(res.data.msg || '服务异常');
      return Promise.reject(res.data);
    }
  },
  (err) => {
    hideLoading();
    if (!err.response) {
      ElMessage.error('网络状态异常');
    } else {
      ElMessage.error(err.response.data.msg || '服务异常');

      // err.response.status http 状态码
      if (err.response.status == 401) {
        router.push('/login');
      }
    }

    return Promise.reject(err);
  }
);

export default instance;

/* 特殊的请求工具 - 不拦截结果，用于登录 */
const special_instance = axios.create({
  baseURL,
  timeout: 30000
});

// 请求拦截器
special_instance.interceptors.request.use(
  (config) => {
    showLoading();
    return config;
  },
  (err) => {
    hideLoading();
    Promise.reject(err);
  }
);

// 响应拦截器
special_instance.interceptors.response.use(
  (res) => {
    hideLoading();
    return res.data;
  },
  (err) => {
    hideLoading();
    if (!err.response) {
      ElMessage.error('网络状态异常');
    } else {
      ElMessage.error(err.response.data.msg || '服务异常');

      // err.response.status http 状态码
      if (err.response.status == 401) {
        router.push('/login');
      }
    }

    return Promise.reject(err);
  }
);

export { special_instance };
